-- GreatPeopleMRLCPopup_Panel
-- Author: yiboy
-- DateCreated: 11/28/2024 12:28:38 AM
--------------------------------------------------------------
-- ===========================================================================
--	Great People Popup
-- ===========================================================================

include("InstanceManager");
include("TabSupport");
include("SupportFunctions");
include("Civ6Common"); --DifferentiateCiv
include("ModalScreen_PlayerYieldsHelper");
include("GameCapabilities");
include("GameEffectsText");
-- ===========================================================================
--	CONSTANTS
-- ===========================================================================
local MAX_BIOGRAPHY_PARAGRAPHS	 = 9;						-- maximum # of paragraphs for a biography
local SIZE_ACTION_ICON			 = 38;

local TAB_SIZE					 = 170;
local TAB_PADDING				 = 10;
local TRAIT_YVANGELISTA				=	'TRAIT_LEADER_LATERAN_DECLARATION';


local m_propertyKey_1				= "MayaRework_LongCount";
local m_propertyKey_2				= "MayaRework_LongCount_Points";
local m_propertyKey_3				= "MayaRework_LongCount_PointsUsed";

local m_IsXP1Active 	=	Modding.IsModActive("1B28771A-C749-434B-9053-D1380C553DE9");
local m_IsXP2Active 	= 	Modding.IsModActive("4873eb62-8ccc-4574-b784-dda455e74e68");
local m_IsHDActive 		=	Modding.IsModActive("521b8777-0977-4859-a5ee-3e411a732e5c");
-- ===========================================================================
--	MEMBERS
-- ===========================================================================
local m_TopPanelConsideredHeight = 0;
local m_greatPersonPanelIM		= InstanceManager:new("PanelInstance",				"Content",	Controls.PeopleStack);

-- Dynamic refresh call member used to override the refresh functionality
local m_RefreshFunc			 = nil;

local m_pGreatPeopleTabInstance	= nil;
local m_pPrevRecruitedTabInstance = nil;

local m_kIsGreatWorkCreator		= {};

local m_sCurrentGreatPeopleClass	= 'CLASS_ALL'; -- Temp

local m_kCacheGreatPersonAvailable;

local m_ePreCost					= 0;

local m_kGreatPeople		;
local m_kData				;
local m_activeBiographyID		= -1;	-- Only allow one open at a time (or very quick exceed font allocation)
local m_activeRecruitInfoID		= -1;	-- Only allow one open at a time (or very quick exceed font allocation)


local m_freeRecruitIndividualID = -1;


local m_displayPlayerID		 = -1; -- What player are we displaying.  Used for looking at different players in autoplay
local m_screenWidth			 = -1;


-- ========================================================================================================================
--	Desc
-- ========================================================================================================================
--长纪历:每个玛雅长纪历的一个博克盾结束时，可以选择一位免费的大科学家、大预言家、大艺术家、大工程师或者大农业家。
-- ========================================================================================================================
--	Utils
-- ========================================================================================================================

function GetMayaLongCountPoints(playerID)
	local pPlayer = Players[playerID]
	if pPlayer == nil then
		return 0
	end

	local property = pPlayer:GetProperty(m_propertyKey_2) or 0;

	return property
end

function GetMayaLongCountPoints_Used(playerID)
	local pPlayer = Players[playerID]
	if pPlayer == nil then
		return 0
	end

	local property = pPlayer:GetProperty(m_propertyKey_3) or 0;

	return property
end

	function HasTrait_Property(sTrait, iPlayer)
		local pPlayer = Players[iPlayer];
		local ePro = pPlayer:GetProperty('PROPERTY_'..sTrait) or 0 
		if ePro > 0 then
			return true
		end
		return false
	end
	
--========================================================================================================================
-- Unused
--========================================================================================================================
	function GetGreatWorkCreator()
		for row in GameInfo.GreatPersonIndividuals() do
			m_kIsGreatWorkCreator[row.GreatPersonIndividualType] = false
		end
		
		for row in GameInfo.GreatWorks() do
			if row.GreatPersonIndividualType then
				m_kIsGreatWorkCreator[row.GreatPersonIndividualType] = true
			end
		end
	end

	function IsAllowedUnit(iUnit, iClass, iIndividual)
		local kUnitInfo = GameInfo.Units[iUnit]
		local kClassInfo = GameInfo.GreatPersonClasses[iClass]
		local kIndividualInfo = GameInfo.GreatPersonIndividuals[iIndividual]
		
		if 	kUnitInfo.FoundReligion then
			return false
		elseif kIndividualInfo.ActionCharges == 0 then
			return false
		elseif m_kIsGreatWorkCreator[kIndividualInfo.GreatPersonIndividualType] then
			return false
		end
		
		return true
	end

--========================================================================================================================
	
	function LocalPlayerTurnBegin()
		if  ContextPtr:IsHidden() then
			SaveTempGreatPersonInfo()
		end
	end
	
--========================================================================================================================

--========================================================================================================================
-- Refresh
--========================================================================================================================
	-- ===========================================================================
	function Refresh()
		--print("0031")
		m_greatPersonPanelIM:ResetInstances()

		--print("0032")

		local mrlc_points = GetMayaLongCountPoints(Game.GetLocalPlayer())
		local mrlc_points_used = GetMayaLongCountPoints_Used(Game.GetLocalPlayer())

		Controls.CurrentPointsTip:SetText(Locale.Lookup("LOC_MAYA_REWORK_LONG_COUNT_CURRENT_POINTS_DETAILS", mrlc_points, mrlc_points_used));	

		RefreshCurrentGreatPeople()

		--print("0033")

	end
	
	-- ===========================================================================
--========================================================================================================================
--Get Data
--========================================================================================================================
-- ===========================================================================
--	Helper to obtain biography text.
--	individualID	index of the great person
--	RETURNS:		oreder table of biography text.
-- ===========================================================================
function GetBiographyTextTable( individualID )

	if individualID == nil then
		return {};
	end

	-- LOC_PEDIA_GREATPEOPLE_PAGE_GREAT_PERSON_INDIVIDUAL_ABU_AL_QASIM_AL_ZAHRAWI_CHAPTER_HISTORY_PARA_1
	-- LOC_PEDIA_GREATPEOPLE_PAGE_GREAT_PERSON_INDIVIDUAL_ABDUS_SALAM_CHAPTER_HISTORY_PARA_3
	local bioPrefix	 = "LOC_PEDIA_GREATPEOPLE_PAGE_";
	local bioName	 = GameInfo.GreatPersonIndividuals[individualID].GreatPersonIndividualType;
	local bioPostfix = "_CHAPTER_HISTORY_PARA_";

	local kBiography = {};
	for i = 1,MAX_BIOGRAPHY_PARAGRAPHS,1 do
		local key = bioPrefix..bioName..bioPostfix..tostring(i);
		if Locale.HasTextKey(key) then
			kBiography[i] = Locale.Lookup(key);
		else
			break;
		end
	end
	return kBiography;
end
-- =======================================================================================
--	Populate a data table with timeline information.
--		data	An allocated table to receive the timeline.
--		isPast	If the data should be from the past (instead of the current)
-- =======================================================================================
function PopulateData( data, isPast )
	
	if data == nil then
		error("GreatPeoplePopup received an empty data in to PopulateData");
		return;
	end
	
	local displayPlayerID  = GetDisplayPlayerID();
	if (displayPlayerID == -1) then
		return;
	end
	--print("populate 0001")

	local pGreatPeople	  = Game.GetGreatPeople();
	if pGreatPeople == nil then
		UI.DataError("GreatPeoplePopup received NIL great people object.");
		return;
	end

	local pTimeline = nil;
	if isPast then
		pTimeline = pGreatPeople:GetPastTimeline();
	else
		pTimeline = pGreatPeople:GetTimeline();
	end
	
	--print("populate 0002")
	
	--时间线上的伟人，只会给现在能招募的伟人的信息（每种类型只给一个)
	for i,entry in ipairs(pTimeline) do
		-- don't add unclaimed great people to the previously recruited tab
		if not isPast or entry.Claimant then
			--print("populate 000200")

			local claimantName  = nil;
			if (entry.Claimant ~= nil) then
				claimantName = Locale.Lookup(PlayerConfigurations[entry.Claimant]:GetCivilizationShortDescription());
			end

			local canRecruit			 = false;
			local canReject				 = false;
			local canPatronizeWithFaith  = false;
			local canPatronizeWithGold	 = false;
			local actionCharges			 = 0;
			local patronizeWithGoldCost	 = nil;		
			local patronizeWithFaithCost = nil;
			local recruitCost			 = entry.Cost;
			local rejectCost			 = nil;
			local earnConditions		 = nil;

			--print("populate 000201")
			if (entry.Individual ~= nil) then
				if (Players[displayPlayerID] ~= nil) then
					canRecruit = pGreatPeople:CanRecruitPerson(displayPlayerID, entry.Individual);
					if (not isPast) then
						canReject = pGreatPeople:CanRejectPerson(displayPlayerID, entry.Individual);
						if (canReject) then
							rejectCost = pGreatPeople:GetRejectCost(displayPlayerID, entry.Individual);
						end
					end

					--print("populate 000202")

					canPatronizeWithGold = pGreatPeople:CanPatronizePerson(displayPlayerID, entry.Individual, YieldTypes.GOLD);
					patronizeWithGoldCost = pGreatPeople:GetPatronizeCost(displayPlayerID, entry.Individual, YieldTypes.GOLD);
					canPatronizeWithFaith = pGreatPeople:CanPatronizePerson(displayPlayerID, entry.Individual, YieldTypes.FAITH);
					patronizeWithFaithCost = pGreatPeople:GetPatronizeCost(displayPlayerID, entry.Individual, YieldTypes.FAITH);
					--这句话用在海军统帅上面，必须有海城或港口城
					earnConditions = pGreatPeople:GetEarnConditionsText(displayPlayerID, entry.Individual);
				end
				local individualInfo = GameInfo.GreatPersonIndividuals[entry.Individual];
				actionCharges = individualInfo.ActionCharges;
			end
			

			--print("populate 000203")

			local personName = "";
			if  GameInfo.GreatPersonIndividuals[entry.Individual] ~= nil then
				personName = Locale.Lookup(GameInfo.GreatPersonIndividuals[entry.Individual].Name);
			end  

			--print("populate 000204")

			local kPerson = {
				IndividualID			= entry.Individual,
				ClassID					= entry.Class,
				EraID					= entry.Era,
				ClaimantID				= entry.Claimant,
				ActionCharges			= actionCharges,
				ActionNameText			= entry.ActionNameText,
				ActionUsageText			= entry.ActionUsageText,
				ActionEffectText		= entry.ActionEffectText,
				BiographyTextTable		= GetBiographyTextTable( entry.Individual ),
				CanPatronizeWithFaith	= canPatronizeWithFaith,
				CanPatronizeWithGold	= canPatronizeWithGold,
				CanReject				= canReject,
				ClaimantName			= claimantName,
				CanRecruit				= canRecruit,
				EarnConditions			= earnConditions,
				Name					= personName,
				PassiveNameText			= entry.PassiveNameText,
				PassiveEffectText		= entry.PassiveEffectText,
				PatronizeWithFaithCost	= patronizeWithFaithCost,
				PatronizeWithGoldCost	= patronizeWithGoldCost,
				RecruitCost				= recruitCost,
				RejectCost				= rejectCost,
				TurnGranted				= entry.TurnGranted
			};
			--print("Name=\t", personName)
			table.insert(data.Timeline, kPerson);		
		end
	end

	--print("populate 0003")

	--每种类型伟人的点数
	for classInfo in GameInfo.GreatPersonClasses() do
		local classID = classInfo.Index;
		local pointsTable = {};
		local players = Game.GetPlayers{Major = true, Alive = true};
		--print("populate 000300")
		for i, player in ipairs(players) do
			local playerName = "";
			local isPlayer = false;

			--print("populate 000301")
			if (player:GetID() == displayPlayerID) then
				playerName = playerName .. Locale.Lookup(PlayerConfigurations[player:GetID()]:GetCivilizationShortDescription());
				isPlayer = true;
			elseif (Game.GetLocalObserver() == PlayerTypes.OBSERVER or Players[displayPlayerID]:GetDiplomacy():HasMet(player:GetID())) then
				playerName = playerName .. Locale.Lookup(PlayerConfigurations[player:GetID()]:GetCivilizationShortDescription());
			else
				playerName = playerName .. Locale.Lookup("LOC_DIPLOPANEL_UNMET_PLAYER");
			end

			--print("populate 000302")

			local playerPoints = {
				IsPlayer			= isPlayer,
				MaxPlayerInstances	= classInfo.MaxPlayerInstances,
				NumInstancesEarned	= pGreatPeople:CountPeopleReceivedByPlayer(classID, player:GetID());
				PlayerName			= playerName,
				PointsTotal			= player:GetGreatPeoplePoints():GetPointsTotal(classID),
				PointsPerTurn		= player:GetGreatPeoplePoints():GetPointsPerTurn(classID),
				PlayerID			= player:GetID()
			};
			--print("populate 000303")
			table.insert(pointsTable, playerPoints);
		end
		--print("populate 000304")
		table.sort(pointsTable, function(a, b)
			if (a.IsPlayer and not b.IsPlayer) then
				return true;
			elseif (not a.IsPlayer and b.IsPlayer) then
				return false;
			end
			return a.PointsTotal > b.PointsTotal;
		end);
		--print("populate 000305")
		data.PointsByClass[classID] = pointsTable;
	end

end

--========================================================================================================================

--========================================================================================================================
function RefreshCurrentGreatPeople()
	local kData 	= {
		Timeline		= {},
		PointsByClass	= {},
	};

	--print("into populate data")

	PopulateData(kData, false);	-- do not use past data
	--print("end populate data")

	--print("into ViewCurrent")
	ViewCurrent(kData);
	--print("end ViewCurrent")

	m_kData = kData;
end
-- ===========================================================================
--	View the great people currently available (to be purchased)
-- ===========================================================================
function ViewCurrent( data )
	if (data == nil) then
		UI.DataError("GreatPeople attempting to view current timeline data but received NIL instead.");
		return;
	end

	--print("ViewCurrent 0000")

	m_kGreatPeople = {};
	ResetGreatPeopleInstances();

	--print("ViewCurrent 0001")

	Controls.PeopleScroller:SetHide(false);

	local kInstanceToShow = nil;

	--print("ViewCurrent 0002")

	for i, kPerson in ipairs(data.Timeline) do	

		--限制只对特定类型生效
		local classID = kPerson.ClassID;
		local classTypeStr = GameInfo.GreatPersonClasses[classID].GreatPersonClassType
		if IsValidGPClass(classTypeStr) then
			AddRecruit(data, kPerson);
		end
	end

	--print("ViewCurrent 0003")

	Controls.PeopleStack:CalculateSize();
	Controls.PeopleScroller:CalculateSize();
	
	m_screenWidth = math.max(Controls.PeopleStack:GetSizeX(), 1024);
	Controls.WoodPaneling:SetSizeX( m_screenWidth );

	-- Clamp overall popup size to not be larger than contents (overspills in 4k and eyefinitiy rigs.)
	local screenX,_			 = UIManager:GetScreenSizeVal();
	if m_screenWidth > screenX then	
		m_screenWidth = screenX;
	end	

	--print("ViewCurrent 0004")
	
	Controls.PopupContainer:SetSizeX( m_screenWidth );
	Controls.ModalFrame:SetSizeX( m_screenWidth );	

	--print("ViewCurrent 0005")

	-- Has an instance been set to auto scroll to?
	Controls.PeopleScroller:SetScrollValue( 0 );		-- Either way reset scroll first (mostly for hot seat)
	if kInstanceToShow ~= nil then
		local contentWidth		 = kInstanceToShow.Content:GetSizeX();
		local contentOffsetx	 = kInstanceToShow.Content:GetScreenOffset();	-- Obtaining normal offset would yield 0, but since modal is as wide as the window, this works.
		local offsetx			 = contentOffsetx + (contentWidth * 0.5) + (m_screenWidth * 0.5);	-- Middle of screen
		local totalWidth		 = Controls.PeopleScroller:GetSizeX();
		local scrollAmt			 =  offsetx / totalWidth;
		scrollAmt = math.clamp( scrollAmt, 0, 1);
		Controls.PeopleScroller:SetScrollValue( scrollAmt );
	end

	--print("ViewCurrent 0006")

	if IsTutorialRunning() then
		Controls.PeopleScroller:SetScrollValue( .3 );
	end

	--print("ViewCurrent 0007")
end

function IsValidGPClass(classTypeStr)
	for row in GameInfo.MayaUA_GreatPersonClasses() do
		if row.GreatPersonClassType == classTypeStr then
			return true
		end
	end
	return false
end
--========================================================================================================================
function AddRecruit( kData, kPerson )

	local instance		 = m_greatPersonPanelIM:GetInstance();
	local classData		 = GameInfo.GreatPersonClasses[kPerson.ClassID];
	local individualData = GameInfo.GreatPersonIndividuals[kPerson.IndividualID];

	--print("AddRecruit 000")

	if (kPerson.ClassID ~= nil) then
		local portrait = "ICON_GENERIC_" .. classData.GreatPersonClassType;
		portrait = portrait:gsub("_CLASS","_INDIVIDUAL");
		instance.Portrait:SetIcon(portrait);
		instance.CircleFlare:SetHide(false);

		local classText = Locale.Lookup(classData.Name);
		instance.ClassName:SetText(classText);
		instance.ClassName:SetHide(false);
	else
		instance.CircleFlare:SetHide(true);
		instance.ClassName:SetHide(true);
	end

	--print("AddRecruit 001")
		
	if kPerson.IndividualID ~= nil then
		local individualName = Locale.ToUpper(kPerson.Name);
		instance.IndividualName:SetText( individualName );
	end

	if kPerson.EraID ~= nil then
		local eraName = Locale.ToUpper(Locale.Lookup(GameInfo.Eras[kPerson.EraID].Name));
		instance.EraName:SetText( eraName );
	end
		
	--print("AddRecruit 002")

	if instance["m_EffectsIM"] ~= nil then
		instance["m_EffectsIM"]:ResetInstances();
	else
		instance["m_EffectsIM"] = InstanceManager:new("EffectInstance",	"Top",	instance.EffectStack);
	end

	--伟人被动效果
	if kPerson.PassiveNameText ~= nil and kPerson.PassiveNameText ~= "" then
		local effectInst	= instance["m_EffectsIM"]:GetInstance();	
		local effectText = kPerson.PassiveEffectText;
		local fullText	= kPerson.PassiveNameText .. "[NEWLINE][NEWLINE]" .. effectText;
		effectInst.Text:SetText( effectText );
		effectInst.EffectTypeIcon:SetToolTipString( fullText );
		effectInst.PassiveAbilityIcon:SetHide(false);
		effectInst.ActiveAbilityIcon:SetHide(true);
	end

	--print("AddRecruit 003")
	--伟人主动效果
	if (kPerson.ActionNameText ~= nil and kPerson.ActionNameText ~= "") then
		local effectInst	= instance["m_EffectsIM"]:GetInstance();			
		local effectText	= kPerson.ActionEffectText;
		local fullText	= kPerson.ActionNameText;			
		if (kPerson.ActionCharges > 0) then
			fullText = fullText .. " (" .. Locale.Lookup("LOC_GREATPERSON_ACTION_CHARGES", kPerson.ActionCharges) .. ")";
		end
		fullText = fullText .. "[NEWLINE]" .. kPerson.ActionUsageText;
		fullText = fullText .. "[NEWLINE][NEWLINE]" .. effectText;
		effectInst.Text:SetText( effectText );
		effectInst.EffectTypeIcon:SetToolTipString( fullText );

		local actionIcon = classData.ActionIcon;
		if actionIcon ~= nil and actionIcon ~= "" then
			local textureOffsetX, textureOffsetY, textureSheet = IconManager:FindIconAtlas(actionIcon, SIZE_ACTION_ICON);
			if(textureSheet == nil or textureSheet == "") then
				UI.DataError("Could not find icon in ViewCurrent: icon=\""..actionIcon.."\", iconSize="..tostring(SIZE_ACTION_ICON) );
			else
				effectInst.ActiveAbilityIcon:SetTexture(textureOffsetX, textureOffsetY, textureSheet);
				effectInst.ActiveAbilityIcon:SetHide(false);
				effectInst.PassiveAbilityIcon:SetHide(true);
			end
		else
			effectInst.ActiveAbilityIcon:SetHide(true);
		end
	end

	--print("AddRecruit 004")

	if instance["m_RecruitIM"] ~= nil then
		instance["m_RecruitIM"]:ResetInstances();
	else
		instance["m_RecruitIM"] = InstanceManager:new("RecruitInstance", "Top", instance.RecruitStack);
	end

	if instance["m_RecruitExtendedIM"] ~= nil then
		instance["m_RecruitExtendedIM"]:ResetInstances();
	else
		instance["m_RecruitExtendedIM"] = InstanceManager:new("RecruitInstance", "Top", instance.RecruitInfoStack);
	end

	--print("AddRecruit 005")

	if kPerson.IndividualID ~= nil and kPerson.ClassID ~= nil then
		
		--默认隐藏金币和信仰购买
		-- Buy via gold
		instance.GoldButton:SetHide(true);

		--if (HasCapability("CAPABILITY_GREAT_PEOPLE_RECRUIT_WITH_GOLD") and (not kPerson.CanRecruit and not kPerson.CanReject and kPerson.PatronizeWithGoldCost ~= nil and kPerson.PatronizeWithGoldCost < 1000000)) then
			--instance.GoldButton:SetText(kPerson.PatronizeWithGoldCost .. "[ICON_Gold]");
			--instance.GoldButton:SetToolTipString(GetPatronizeWithGoldTT(kPerson));
			--instance.GoldButton:SetVoid1(kPerson.IndividualID);
			--instance.GoldButton:RegisterCallback(Mouse.eLClick, OnGoldButtonClick);
			--instance.GoldButton:SetDisabled((not kPerson.CanPatronizeWithGold) or IsReadOnly());
			--instance.GoldButton:SetHide(false);
		--else
			--instance.GoldButton:SetHide(true);
		--end
		--print("AddRecruit 00501")

		-- Buy via Faith
		instance.FaithButton:SetHide(true);
		--if (HasCapability("CAPABILITY_GREAT_PEOPLE_RECRUIT_WITH_FAITH") and (not kPerson.CanRecruit and not kPerson.CanReject and kPerson.PatronizeWithFaithCost ~= nil and kPerson.PatronizeWithFaithCost < 1000000)) then
			--instance.FaithButton:SetText(kPerson.PatronizeWithFaithCost .. "[ICON_Faith]");
			--instance.FaithButton:SetToolTipString(GetPatronizeWithFaithTT(kPerson));
			--instance.FaithButton:SetVoid1(kPerson.IndividualID);
			--instance.FaithButton:RegisterCallback(Mouse.eLClick, OnFaithButtonClick);
			--instance.FaithButton:SetDisabled((not kPerson.CanPatronizeWithFaith) or IsReadOnly());
			--instance.FaithButton:SetHide(false);
		--else
			--instance.FaithButton:SetHide(true);
		--end

		--print("AddRecruit 00502")


		--默认显示招募按钮，但是如果没有点数，则为灰色
		local mrlc_points = GetMayaLongCountPoints(Game.GetLocalPlayer())
		local mrlc_points_used = GetMayaLongCountPoints_Used(Game.GetLocalPlayer())

		-- Recruiting 
		if (HasCapability("CAPABILITY_GREAT_PEOPLE_CAN_RECRUIT") and kPerson.RecruitCost ~= nil) then
			
			instance.RecruitButton:SetHide(false);

			if mrlc_points > 0 and mrlc_points > mrlc_points_used then
				instance.RecruitButton:SetToolTipString( Locale.Lookup("LOC_MAYA_REWORK_LONG_COUNT_FREE_RECRUIT_DETAILS") );
				instance.RecruitButton:SetVoid1(kPerson.IndividualID);
				instance.RecruitButton:SetVoid2(kPerson.RecruitCost);
				instance.RecruitButton:RegisterCallback(Mouse.eLClick, OnRecruitButtonClick);

				instance.RecruitButton:SetDisabled(false);
			else
				instance.RecruitButton:SetDisabled(true);
				instance.RecruitButton:SetToolTipString( Locale.Lookup("LOC_MAYA_REWORK_LONG_COUNT_FREE_RECRUIT_FAIL_REASON") );
			end

			--print("situation 1")

			-- Auto scroll to first recruitable person.
			if kInstanceToShow==nil then
				kInstanceToShow = instance;
			end
		else
			instance.RecruitButton:SetHide(true);
			--print("situation 2")
		end

		--print("AddRecruit 00503")

		--现在无法拒绝
		instance.RejectButton:SetHide(true);

		-- Rejecting
		--if (HasCapability("CAPABILITY_GREAT_PEOPLE_CAN_REJECT") and kPerson.CanReject and kPerson.RejectCost ~= nil) then
			--instance.RejectButton:SetToolTipString( Locale.Lookup("LOC_GREAT_PEOPLE_PASS_DETAILS", kPerson.RejectCost ) );
			--instance.RejectButton:SetVoid1(kPerson.IndividualID);
			--instance.RejectButton:RegisterCallback(Mouse.eLClick, OnRejectButtonClick);
			--instance.RejectButton:SetHide(false);
		--else
			--instance.RejectButton:SetHide(true);
		--end

		--print("AddRecruit 00504")

		-- If Recruit or Reject buttons are shown hide the minimized recruit stack
		if not instance.RejectButton:IsHidden() or not instance.RecruitButton:IsHidden() then
			instance.RecruitMinimizedStack:SetHide(true);
		else
			instance.RecruitMinimizedStack:SetHide(false);
		end

		--print("AddRecruit 00505")
			
		-- Recruiting standings
		-- Let's sort the table first by points total, then by the lower player id (to push yours toward the top of the list for readability)
		local recruitTable = {};
		for i, kPlayerPoints in ipairs(kData.PointsByClass[kPerson.ClassID]) do
			table.insert(recruitTable,kPlayerPoints);
		end
		table.sort(recruitTable,
			function (a,b) 
				if(a.PointsTotal == b.PointsTotal) then
					return a.PlayerID < b.PlayerID;
				else
					return a.PointsTotal > b.PointsTotal;
				end 
				end);

		--print("AddRecruit 00506")

		for i, kPlayerPoints in ipairs(recruitTable) do	
			if (kPlayerPoints.PlayerID == Game.GetLocalPlayer()) then
				FillRecruitInstance(instance.LocalPlayerRecruitInstance, kPlayerPoints, kPerson, classData);
			else
				local recruitInst = instance["m_RecruitIM"]:GetInstance();
				FillRecruitInstance(recruitInst, kPlayerPoints, kPerson, classData);
			end

			local recruitExtendedInst = instance["m_RecruitExtendedIM"]:GetInstance();
			FillRecruitInstance(recruitExtendedInst, kPlayerPoints, kPerson, classData);
		end

		--print("AddRecruit 00507")

		--禁止招募的原因，如果禁止招募，则隐藏按钮（对于大预言家和海军统帅）
		if (kPerson.EarnConditions ~= nil and kPerson.EarnConditions ~= "") then
			instance.RecruitInfo:SetText("[COLOR_Civ6Red]" .. Locale.Lookup("LOC_GREAT_PEOPLE_CANNOT_EARN_PERSON") .. "[ENDCOLOR]");
			instance.RecruitInfo:SetToolTipString("[COLOR_Civ6Red]" .. kPerson.EarnConditions .. "[ENDCOLOR]");
			instance.RecruitInfo:SetHide(false);

			instance.RecruitButton:SetHide(true);
		else
			instance.RecruitInfo:SetHide(true);
		end

		instance.RecruitScroll:CalculateSize();
	end

	--print("AddRecruit 006")

		
	if kPerson.IndividualID ~= nil then
		-- Set the biography buttons
		instance.BiographyBackButton:SetVoid1( kPerson.IndividualID );
		instance.BiographyBackButton:RegisterCallback( Mouse.eLClick, OnBiographyClick );
		instance.BiographyOpenButton:SetVoid1( kPerson.IndividualID );
		instance.BiographyOpenButton:RegisterCallback( Mouse.eLClick, OnBiographyClick );
			
		-- Setup extended recruit info buttons
		instance.RecruitInfoOpenButton:SetVoid1( kPerson.IndividualID );
		instance.RecruitInfoOpenButton:RegisterCallback( Mouse.eLClick, OnRecruitInfoClick );
		instance.RecruitInfoBackButton:SetVoid1( kPerson.IndividualID );
		instance.RecruitInfoBackButton:RegisterCallback( Mouse.eLClick, OnRecruitInfoClick );

		m_kGreatPeople[kPerson.IndividualID] = instance; -- Store instance for later look up
	end

	--print("AddRecruit 007")

	local noneAvailable		 = (kPerson.IndividualID == nil);
	instance.IndividualName:SetHide( noneAvailable );
	instance.EraName:SetHide( noneAvailable );
	instance.MainInfo:SetHide( noneAvailable );
	instance.BiographyBackButton:SetHide( noneAvailable );
	instance.ClaimedLabel:SetHide( not noneAvailable );
	instance.BiographyArea:SetHide( true );
	instance.RecruitInfoArea:SetHide( true );
	instance.FadedBackground:SetHide( true );
	instance.BiographyOpenButton:SetHide( noneAvailable );
		
	instance.EffectStack:CalculateSize();
	instance.EffectStackScroller:CalculateSize();
end
--========================================================================================================================
function ResetGreatPeopleInstances()
	m_greatPersonPanelIM:ResetInstances();
end
--========================================================================================================================
function FillRecruitInstance(instance, playerPoints, personData, classData)
	instance.Country:SetText( playerPoints.PlayerName );
	
	instance.Amount:SetText( tostring(Round(playerPoints.PointsTotal,1)) .. "/" .. tostring(personData.RecruitCost) );
	local progressPercent  = Clamp( playerPoints.PointsTotal / personData.RecruitCost, 0, 1 );
	instance.ProgressBar:SetPercent( progressPercent );
	
	local recruitColorName = "GreatPeopleCS";
	if playerPoints.IsPlayer then
		recruitColorName = "GreatPeopleActiveCS";			
	end
	instance.Amount:SetColorByName( recruitColorName );
	instance.Country:SetColorByName( recruitColorName );
	instance.Country:SetColorByName( recruitColorName );
	instance.ProgressBar:SetColorByName( recruitColorName );

	DifferentiateCiv(playerPoints.PlayerID,instance.CivIcon,instance.CivIcon,instance.CivBacking, nil, nil, Game.GetLocalPlayer());

	local recruitDetails = Locale.Lookup("LOC_GREAT_PEOPLE_POINT_DETAILS", Round(playerPoints.PointsPerTurn, 1), classData.IconString, classData.Name);
	instance.Top:SetToolTipString(recruitDetails);
end

function GetPatronizeWithGoldTT(kPerson)
	return Locale.Lookup("LOC_GREAT_PEOPLE_PATRONAGE_GOLD_DETAILS", kPerson.PatronizeWithGoldCost);
end

function GetPatronizeWithFaithTT(kPerson)
	return Locale.Lookup("LOC_GREAT_PEOPLE_PATRONAGE_FAITH_DETAILS", kPerson.PatronizeWithFaithCost);
end

-- =======================================================================================
-- Toggle Extended Recruit Info whether open or closed
-- =======================================================================================
function OnRecruitInfoClick( individualID )
	-- If a recruit info is open, close the last opened
	if m_activeRecruitInfoID ~= -1 and individualID ~= m_activeRecruitInfoID then
		OnRecruitInfoClick( m_activeRecruitInfoID );		
	end
	
	local instance= m_kGreatPeople[individualID];
	if instance == nil then
		print("WARNING: Was unable to find instance for individual \""..tostring(individualID).."\"");
		return;
	end

	local isShowingRecruitInfo = not instance.RecruitInfoArea:IsHidden();

	instance.BiographyArea:SetHide( true );
	instance.RecruitInfoArea:SetHide( isShowingRecruitInfo );
	instance.MainInfo:SetHide( not isShowingRecruitInfo );
	instance.FadedBackground:SetHide( isShowingRecruitInfo );
	instance.BiographyOpenButton:SetHide( not isShowingRecruitInfo );

	if isShowingRecruitInfo then	
		m_activeRecruitInfoID = -1;
	else
		m_activeRecruitInfoID = individualID;
	end
end
--========================================================================================================================
--  Button Callback
-- =======================================================================================
--	Button Callback
--	Switch between biography and stats for a great person
-- =======================================================================================
function OnBiographyClick( individualID )

	-- If a biography is open, close it via recursive magic...
	if m_activeBiographyID ~= -1 and individualID ~= m_activeBiographyID then
		OnBiographyClick( m_activeBiographyID );		
	end

	local instance= m_kGreatPeople[individualID];
	if instance == nil then
		print("WARNING: Was unable to find instance for individual \""..tostring(individualID).."\"");
		return;
	end

	local isShowingBiography	 = not instance.BiographyArea:IsHidden();
	local buttonLabelText		;

	instance.BiographyArea:SetHide( isShowingBiography );
	instance.RecruitInfoArea:SetHide( true );
	instance.MainInfo:SetHide( not isShowingBiography );
	instance.FadedBackground:SetHide( isShowingBiography );
	instance.BiographyOpenButton:SetHide( not isShowingBiography );

	if isShowingBiography then
		-- Current showing; so hide...		
		m_activeBiographyID = -1;
	else
		-- Current hidden, show biography...
		m_activeBiographyID = individualID;		

		-- Get data
		local kBiographyText;
		for k,v in pairs(m_kData.Timeline) do
			if v.IndividualID == individualID then
				kBiographyText = v.BiographyTextTable;
				break;
			end
		end
		if kBiographyText ~= nil then
			instance.BiographyText:SetText( table.concat(kBiographyText, "[NEWLINE][NEWLINE]"));
		else
			instance.BiographyText:SetText("");
			print("WARNING: Couldn't find data for \""..tostring(individualID).."\"");			
		end
		
		instance.BiographyScroll:CalculateSize();
	end	
end

--========================================================================================================================
-- ===========================================================================
function OnRecruitButtonClick( individualID, costGPP)
	Events.GreatPeoplePointsChanged.Add( OnGreatPersonPointsChanged_MRLC );

	local pLocalPlayer = Players[Game.GetLocalPlayer()];
	if (pLocalPlayer ~= nil) then
		m_freeRecruitIndividualID = individualID

		local individualInfo = GameInfo.GreatPersonIndividuals[individualID]
		local classTypeStr = individualInfo.GreatPersonClassType
		local classInfo = GameInfo.GreatPersonClasses[classTypeStr];

		local tParameters = {}
		tParameters['OnStart'] 		= 'MayaReworkLongCount_ChangeGPP';
		tParameters['hClassID'] 		= classInfo.Index;
		tParameters['hCost'] 		= costGPP;
		UI.RequestPlayerOperation(Game.GetLocalPlayer(), PlayerOperations.EXECUTE_SCRIPT, tParameters)
		Close();
		print("free recruit 001")
	end
end

function OnGreatPersonPointsChanged_MRLC()
	local pLocalPlayer = Players[Game.GetLocalPlayer()];
	if (pLocalPlayer ~= nil) and m_freeRecruitIndividualID > 0 then
		local kParameters = {};
		kParameters[PlayerOperations.PARAM_GREAT_PERSON_INDIVIDUAL_TYPE] = m_freeRecruitIndividualID;
		UI.RequestPlayerOperation(Game.GetLocalPlayer(), PlayerOperations.RECRUIT_GREAT_PERSON, kParameters);

		--然后对玩家设置属性，用来关联天文台

		--先获取产出类型
		local individualID = m_freeRecruitIndividualID
		local individualInfo = GameInfo.GreatPersonIndividuals[individualID]
		local classTypeStr = individualInfo.GreatPersonClassType
		local yield_type = GameInfo.MayaUA_GreatPersonClasses[classTypeStr].YieldType

		local tParameters = {}
		tParameters['OnStart'] 		= 'MayaReworkLongCount_SetProperty';
		tParameters['Key'] 			= "MRLC_" .. yield_type .."_PROPERTY"
		tParameters['Value'] 		= 1
		tParameters['m_IsHDActive'] 		= m_IsHDActive


		-- 首次招募该类型的伟人时触发效果
		if not pLocalPlayer:GetProperty('onSixSkyGetLongCountGPP'..classTypeStr) and pLocalPlayer:GetProperty('MayaRework_SixSky') then
			tParameters['classTypeStr'] 		= classTypeStr
		end
		UI.RequestPlayerOperation(Game.GetLocalPlayer(), PlayerOperations.EXECUTE_SCRIPT, tParameters)

		m_freeRecruitIndividualID = -1
	end

	Events.GreatPeoplePointsChanged.Remove( OnGreatPersonPointsChanged_MRLC );
	print("free recruit 003")
end

-- ===========================================================================
function OnRejectButtonClick( individualID )
	local pLocalPlayer = Players[Game.GetLocalPlayer()];
	if (pLocalPlayer ~= nil) then
		local kParameters = {};
		kParameters[PlayerOperations.PARAM_GREAT_PERSON_INDIVIDUAL_TYPE] = individualID;
		UI.RequestPlayerOperation(Game.GetLocalPlayer(), PlayerOperations.REJECT_GREAT_PERSON, kParameters);
		Close();
	end
end

-- ===========================================================================
function OnGoldButtonClick( individualID  )
	local pLocalPlayer = Players[Game.GetLocalPlayer()];
	if (pLocalPlayer ~= nil) then
		local kParameters = {};
		kParameters[PlayerOperations.PARAM_GREAT_PERSON_INDIVIDUAL_TYPE] = individualID;
		kParameters[PlayerOperations.PARAM_YIELD_TYPE] = YieldTypes.GOLD;
		UI.RequestPlayerOperation(Game.GetLocalPlayer(), PlayerOperations.PATRONIZE_GREAT_PERSON, kParameters);
		UI.PlaySound("Purchase_With_Gold");
		Close();
	end
end

-- ===========================================================================
function OnFaithButtonClick( individualID  )
	local pLocalPlayer = Players[Game.GetLocalPlayer()];
	if (pLocalPlayer ~= nil) then
		local kParameters = {};
		kParameters[PlayerOperations.PARAM_GREAT_PERSON_INDIVIDUAL_TYPE] = individualID;
		kParameters[PlayerOperations.PARAM_YIELD_TYPE] = YieldTypes.FAITH;
		UI.RequestPlayerOperation(Game.GetLocalPlayer(), PlayerOperations.PATRONIZE_GREAT_PERSON, kParameters);
		UI.PlaySound("Purchase_With_Faith");
		Close();
	end
end
-- ===========================================================================
-- FOR OVERRIDE
-- ===========================================================================
function IsReadOnly()
	return false;
end
-- ===========================================================================
function ChangeDisplayPlayerID(bBackward)
	
	if (bBackward == nil) then
		bBackward = false;
	end

	local aPlayers = PlayerManager.GetAliveMajors();
	local playerCount = #aPlayers;

	-- Anything set yet?
	if (m_displayPlayerID ~= -1) then
		-- Loop and find the current player and skip to the next
		for i, pPlayer in ipairs(aPlayers) do
			if (pPlayer:GetID() == m_displayPlayerID) then

				if (bBackward) then
					-- Have a previous one?
					if (i >= 2) then
						-- Yes
						m_displayPlayerID = aPlayers[ playerCount ]:GetID();
					else
						-- Go to the end
						m_displayPlayerID = aPlayers[1]:GetID();
					end
				else
					-- Have a next one?
					if (#aPlayer > i) then
						-- Yes
						m_displayPlayerID = aPlayers[i + 1]:GetID();
					else
						-- Back to the beginning
						m_displayPlayerID = aPlayers[1]:GetID();
					end
				end

				return m_displayPlayerID;
			end
		end

	end

	-- No player, or didn't find the previous player, start from the beginning.
	if (playerCount > 0) then
		m_displayPlayerID = aPlayers[1]:GetID();
	end

	return m_displayPlayerID;
end
				
-- ===========================================================================
function GetDisplayPlayerID()

	if Automation.IsActive() then
		if (m_displayPlayerID ~= -1) then
			return m_displayPlayerID;
		end

		return ChangeDisplayPlayerID();
	end

	return Game.GetLocalPlayer();
end

-- ===========================================================================
-- ===========================================================================
function OnTogglePanel()
	
	if ContextPtr:IsHidden() then
		Open()
	else
		Close()
	end
end
-- ===========================================================================
function Open()
	--print("into open")
	if (Game.GetLocalPlayer() == -1) then
		return
	end
	
	m_ePreCost = 0;

	--ContextPtr:SetHide(false);
	
	print("001")

	if not UIManager:IsInPopupQueue(ContextPtr) then
		-- Queue the screen as a popup, but we want it to render at a desired location in the hierarchy, not on top of everything.
        local kParameters = {};
        kParameters.RenderAtCurrentParent = true;
        kParameters.InputAtCurrentParent = true;
        kParameters.AlwaysVisibleInQueue = true;
        UIManager:QueuePopup(ContextPtr, PopupPriority.Low, kParameters);
        UI.PlaySound("UI_Screen_Open");
    end
	
	--print("002")
	Refresh();

	print("004")

	Controls.ScreenAnimIn:SetToBeginning();
	Controls.ScreenAnimIn:Play();

	-- From ModalScreen_PlayerYieldsHelper
	if not RefreshYields() then
		Controls.Vignette:SetSizeY(m_TopPanelConsideredHeight);
	end
	CloseOtherPanels()

	LuaEvents.MRLC_OpenPanel();
end

function Close()
	if not ContextPtr:IsHidden() then
		UI.PlaySound("UI_Screen_Close");
		--m_Music_IM:DestroyInstances()

	end
		
	UIManager:DequeuePopup(ContextPtr);

	LuaEvents.MRLC_ClosePanel(); -- Tell other UI's (e.g., LaunchBar) this is closed
end

-- ===========================================================================
function CloseOtherPanels()
    LuaEvents.LaunchBar_CloseTechTree()
    LuaEvents.LaunchBar_CloseCivicsTree()
    LuaEvents.LaunchBar_CloseGovernmentPanel()
    LuaEvents.LaunchBar_CloseReligionPanel()
    LuaEvents.LaunchBar_CloseGreatPeoplePopup()
    LuaEvents.LaunchBar_CloseGreatWorksOverview()
    if m_IsXP1Active then
        LuaEvents.GovernorPanel_Close()
        LuaEvents.HistoricMoments_Close()
    end
    if m_IsXP2Active then
        LuaEvents.Launchbar_Expansion2_ClimateScreen_Close()
    end
end

-- =======================================================================================
--	UI Event
-- =======================================================================================
function OnInit( isReload )
	if isReload then
        --Open()
		local takeplace = 0
    end
end

function OnInputHandler(pInputStruct)
	local uiMsg = pInputStruct:GetMessageType();
	if uiMsg == KeyEvents.KeyUp and pInputStruct:GetKey() == Keys.VK_ESCAPE then
		if not ContextPtr:IsHidden() then
			OnTogglePanel()
		end
		return true;
	end
	return false;
end

-- =======================================================================================
--	Initialize
-- =======================================================================================
function Initialize()
	
	-- Prep
	--GetGreatWorkCreator();

	-- Note past great people
	--Events.UnitGreatPersonCreated.Add(InsertRecruitableGreatPeople);
	
	--Events.LocalPlayerTurnBegin.Add(LocalPlayerTurnBegin)
	
	
	-- UI Events
	ContextPtr:SetInitHandler( OnInit );
	ContextPtr:SetInputHandler( OnInputHandler, true );

	-- UI Controls
	-- We use a separate BG within the PeopleScroller control since it needs to scroll with the contents
	Controls.ModalBG:SetHide(true);
	Controls.ModalScreenClose:RegisterCallback(Mouse.eLClick, Close);
	Controls.ModalScreenTitle:SetText(Locale.ToUpper(Locale.Lookup('LOC_MAYA_REWORK_LONG_COUNT_PANEL_TITLE')));

	-- LUA Events
	LuaEvents.MRLC_TogglePopup.Add( OnTogglePanel );

	
	
	
	-- Other Panels Popup
	LuaEvents.DiplomacyActionView_HideIngameUI.Add(Close);
    LuaEvents.EndGameMenu_Shown.Add(Close);
    LuaEvents.FullscreenMap_Shown.Add(Close);
    LuaEvents.NaturalWonderPopup_Shown.Add(Close);
    LuaEvents.ProjectBuiltPopup_Shown.Add(Close);
    LuaEvents.Tutorial_ToggleInGameOptionsMenu.Add(Close);
    LuaEvents.WonderBuiltPopup_Shown.Add(Close);
    LuaEvents.NaturalDisasterPopup_Shown.Add(Close);
    LuaEvents.RockBandMoviePopup_Shown.Add(Close);
	LuaEvents.CivicsTree_OpenCivicsTree.Add(Close);	
	LuaEvents.Government_OpenGovernment.Add(Close);
	LuaEvents.GovernorPanel_Opened.Add(Close);	
	LuaEvents.GreatPeople_OpenGreatPeople.Add(Close);
	LuaEvents.GreatWorks_OpenGreatWorks.Add(Close);
	LuaEvents.HistoricMoments_Opened.Add(Close);
	LuaEvents.Religion_OpenReligion.Add(Close);	
	LuaEvents.PantheonChooser_OpenReligion.Add(Close);	
	LuaEvents.TechTree_OpenTechTree.Add(Close);
	LuaEvents.ClimateScreen_Opened.Add(Close);
	
	
	
	
	m_TopPanelConsideredHeight = Controls.Vignette:GetSizeY() - TOP_PANEL_OFFSET;
end


Initialize();
print("Maya Rework Long Count Panel Initialized!")